package com.treasure.mall.biz.service.core.live.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.BaseSearchCondition;
import com.treasure.mall.biz.dto.live.LiveRoomUserSaveDTO;
import com.treasure.mall.biz.entity.live.LiveRoomUserPO;
import com.treasure.mall.biz.entity.live.LiveRoomUserPO_;
import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.biz.entity.user.UserPO_;
import com.treasure.mall.biz.remote.live.TencentIMService;
import com.treasure.mall.biz.remote.live.enums.MessageType;
import com.treasure.mall.biz.repository.live.LiveRoomUserRepository;
import com.treasure.mall.biz.service.core.blacklist.BlacklistService;
import com.treasure.mall.biz.service.core.live.LiveRoomUserRecordsService;
import com.treasure.mall.biz.service.core.live.LiveRoomUserService;
import com.treasure.mall.biz.service.core.user.UserService;
import com.treasure.mall.zbq.common.ienum.SystemEnums;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * <p>
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.biz.service.core.live.impl
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/9/16 6:57 下午
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 *
 */
@Service
public class LiveRoomUserServiceImpl extends AbstractSearchableCrudService<LiveRoomUserPO, Long> implements LiveRoomUserService {

    private LiveRoomUserRepository liveRoomUserRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private TencentIMService imService;
    @Autowired
    private LiveRoomUserRecordsService liveRoomUserRecordsService;
    @Autowired
    private BlacklistService blacklistService;

    protected LiveRoomUserServiceImpl(LiveRoomUserRepository repository) {
        super(repository);
        liveRoomUserRepository = repository;
    }

    @Override
    protected SpecificationAndSort<LiveRoomUserPO> specificationAndSort(BaseSearchDTO searchDTO) {
        BaseSearchCondition condition = (BaseSearchCondition) searchDTO;
        Specification<LiveRoomUserPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(cb.equal(root.get(LiveRoomUserPO_.deleted), false));
            if (StringUtils.isNotBlank(condition.getMobile())) {
                predicates.add(cb.or(
                        cb.like(root.get(LiveRoomUserPO_.user).get(UserPO_.mobile), likeLeft(condition.getMobile())),
                        cb.like(root.get(LiveRoomUserPO_.user).get(UserPO_.nickName), likeAll(condition.getMobile())))
                );
            }

            if (StringUtils.isNotBlank(condition.getKeyword())) {
                predicates.add(cb.equal(root.get(LiveRoomUserPO_.sessionId), condition.getKeyword()));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "id");
        return new SpecificationAndSort<>(specification, sort);
    }


    /**
     * 检查是否禁言
     *
     * @param userId    用户ID
     * @param sessionId 直播间场次ID
     * @return
     */
    @Override
    public boolean checkForbid(Long userId, String sessionId) {
        //检查是否在黑名单中
        if (blacklistService.checkByUserId(userId, SystemEnums.BlacklistType.LIVE_ROOM)) {
            return true;
        }
        return liveRoomUserRepository.countBySessionIdAndUser_UserIdAndForbidIsTrue(sessionId, userId) > 0;
    }

    /**
     * 设置禁言
     *
     * @param userId    用户ID
     * @param sessionId 直播间场次ID
     * @param forbid    是否禁言
     * @return
     */
    @Override
    public boolean setForbid(Long userId, String sessionId, boolean forbid) {
        LiveRoomUserPO po = liveRoomUserRepository.findFirstByUser_UserIdAndSessionId(userId, sessionId);
        if (po == null || po.isForbid() == forbid) {
            return false;
        }
        liveRoomUserRepository.modifyUserForbid(sessionId, userId, forbid);
        //发送禁言消息
        imService.sendForbidMessage(sessionId, userId, forbid ? MessageType.enableForbid : MessageType.closeForbid);
        return true;
    }

    /**
     * 设置禁言
     *
     * @param id     直播间用户主键ID
     * @param forbid 是否禁言
     * @return
     */
    @Override
    public boolean setForbid(Long id, boolean forbid) {
        LiveRoomUserPO po = this.findById(id);
        if (po == null || po.isForbid() == forbid) {
            return false;
        }
        liveRoomUserRepository.modifyUserForbid(po.getId(), forbid);
        //发送禁言消息
        imService.sendForbidMessage(po.getSessionId(), po.getUser().getUserId(), forbid ? MessageType.enableForbid : MessageType.closeForbid);
        return true;
    }


    @Override
    public LiveRoomUserPO save(BaseSaveDTO saveDTO) {
        try {
            LiveRoomUserSaveDTO dto = (LiveRoomUserSaveDTO) saveDTO;
            UserPO user = userService.findById(dto.getUserId());
            if (user == null) {
                return null;
            }
            LiveRoomUserPO po = liveRoomUserRepository.findFirstByUser_UserIdAndSessionId(dto.getUserId(), dto.getSessionId());
            if (po != null) {
                liveRoomUserRepository.modifyUserOnline(dto.getSessionId(), dto.getUserId());
                //添加进入直播间记录
                liveRoomUserRecordsService.enter(dto.getUserId(), dto.getSessionId());
                return po;
            }
            po = new LiveRoomUserPO();
            po.setOnline(true);
            po.setFirstEnterTime(LocalDateTime.now());
            po.setSessionId(dto.getSessionId());
            po.setForbid(false);
            po.setUser(userService.findById(dto.getUserId()));
            po.setUserOnlineTotalSeconds(0);
            po.setEnterCount(1);
            save(po);
            //添加进入直播间记录
            liveRoomUserRecordsService.enter(dto.getUserId(), dto.getSessionId());
            return po;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 设置离线状态
     *
     * @param userId    用户ID
     * @param sessionId 直播间场次ID
     */
    @Override
    public void modifyUserOffline(Long userId, String sessionId) {
        liveRoomUserRepository.modifyUserOffline(sessionId, userId, LocalDateTime.now());
        //添加离开直播间记录
        liveRoomUserRecordsService.leave(userId, sessionId);
    }

    /**
     * 设置用户上线，不计观看次数
     *
     * @param userId
     * @param sessionId
     */
    @Override
    public void modifyUserOnline(Long userId, String sessionId) {
        liveRoomUserRepository.modifyUserOnlineNoEnterCount(sessionId, userId);
    }

    /**
     * 修改用户在线时长
     *
     * @param userId    用户
     * @param sessionId 直播场次
     * @param seconds   时长，秒
     */
    @Override
    public void modifyUserOnlineDuration(Long userId, String sessionId, Long seconds) {
        liveRoomUserRepository.modifyUserOnlineDuration(sessionId, userId, seconds);
    }


}
